'''
# Coding:utf-8
# Project: iiop
# Author: rtf
# Time: 2021-04-16 14:20:13
# FileName: dynamic_word.py
# Software: PyCharm
'''

import base64
import docx
import bs4
import datetime
from docx.shared import Pt, Cm, Inches
from docx.oxml.ns import qn
from docx.enum.text import WD_ALIGN_PARAGRAPH
from bs4 import BeautifulSoup
from func.root_path import get_path


IMAGE_MIME_TYPE = {"image/gif": "gif",
                   "image/png": "png",
                   "image/jpeg": "jpg",
                   "image/svg+xml": "svg"}


def save_image(img_str, image_name):
    mime_type = img_str[img_str.find(":") + 1:img_str.find(";")]
    img_str = img_str[len(mime_type) + 13:]
    img_data = base64.b64decode(img_str)
    filename = f'{get_path()}/images/{image_name}.{IMAGE_MIME_TYPE.get(mime_type)}'
    with open(filename, 'wb') as f:
        f.write(img_data)
        f.close()
    return filename


def dynamic_process(html_content, title, docx_path, level="first"):
    doc = docx.Document(docx_path)

    if "总论" in title:
        doc.add_page_break()

    p = doc.add_paragraph()
    run = p.add_run(title)
    run.font.size = Pt(16)
    run.font.name = "仿宋_GB2312"
    run._element.rPr.rFonts.set(qn('w:eastAsia'), "仿宋_GB2312")
    if level == "child":
        p_format = p.paragraph_format
        p_format.first_line_indent = Inches(0.2)

        if html_content:
            soup = BeautifulSoup(html_content, 'html.parser')
            soup.prettify()
            for i in range(0, len(soup.contents)):
                if isinstance(soup.contents[i], bs4.element.Tag):
                    p_style = str_to_json(soup.contents[i].attrs.get("style"))
                    text = str()
                    if not isinstance(soup.contents[i].span, int) and soup.contents[i].span:  # 文本
                        for child in soup.contents[i].descendants:
                            if isinstance(child, bs4.element.NavigableString) and child:
                                text += child
                            else:
                                style = str_to_json(child.attrs.get("style"))
                        p = doc.add_paragraph()
                        run = p.add_run(text)  # 使用add_run添加文字
                        if style:
                            if style.get("font-size"):
                                run.font.size = Pt(int(float(style.get("font-size")[:-2])))
                            run.font.name = style.get("font-family")
                            if run._element.rPr.rFonts:
                                run._element.rPr.rFonts.set(qn('w:eastAsia'), style.get("font-family"))
                            if p_style:
                                # 首行缩进
                                if p_style.get("text-indent"):
                                    p.paragraph_format.first_line_indent = Pt(int(float(p_style.get("text-indent")[:-2])))
                                if p_style.get("line-height"):
                                    p.paragraph_format.line_spacing = Pt(int(float(p_style.get("line-height")[:-2])))
                    elif not isinstance(soup.contents[i].tbody, int) and soup.contents[i].tbody:  # 表格
                        cols = 0
                        for child in soup.contents[i].tbody.children:
                            temp_cols = str(child).count("</td>")
                            if temp_cols > cols:
                                cols = temp_cols
                        rows = str(soup.contents[i].tbody).count("</tr>")
                        table = doc.add_table(rows=rows, cols=cols, style='Table Grid')  # 添加一个空表
                        str_line = 0
                        merge_list = list()
                        for row in range(0, len(soup.contents[i].tbody.contents)):
                            soup_row = soup.contents[i].tbody.contents[row]
                            temp_cols = str(soup_row).count("</td>")
                            if isinstance(soup_row, bs4.element.Tag):
                                newline = 0
                                for col in range(0, len(soup_row.contents)):
                                    soup_col = soup_row.contents[col]
                                    if soup_col != "\n":
                                        newline += 1

                                    # 实际列位置 = 原始位置 - 换行
                                    # 实际行位置 = 原始位置 - 空行
                                    real_col = col - newline
                                    real_row = row - str_line
                                    if isinstance(soup_col, bs4.element.Tag):
                                        attrs = soup_col.attrs
                                        colspan = int(attrs.get("colspan")) if attrs.get("colspan") else None
                                        rowspan = int(attrs.get("rowspan")) if attrs.get("rowspan") else None
                                        if colspan and rowspan:
                                            for r in range(real_row, rowspan):
                                                for c in range(1, colspan):
                                                    table.cell(r, real_col).merge(table.cell(r, real_col+c))
                                                    table.cell(real_row, real_col).text = soup_col.text

                                            for r in range(real_row, rowspan):
                                                for c in range(real_col, real_col + colspan):
                                                    merge_list.append((r, c))
                                        elif rowspan:
                                            merge_rowspan = int(rowspan) - 1
                                            table.cell(real_row, real_col).merge(table.cell(real_row + merge_rowspan, real_col))
                                            table.cell(real_row, real_col).text = soup_col.text
                                            for r in range(real_row, real_row + rowspan):
                                                merge_list.append((r, real_col))
                                        elif colspan:
                                            merge_colspan = int(colspan) - 1
                                            table.cell(real_row, real_col).merge(table.cell(real_row, real_col + merge_colspan))
                                            table.cell(real_row, real_col).text = soup_col.text
                                            for c in range(real_col, real_col + colspan):
                                                merge_list.append((real_row, c))
                                        else:  # 单元格赋值
                                            if temp_cols < cols:  # 是否有合并单元格
                                                whether_shift = False
                                                for m in merge_list:
                                                    if m[0] == real_row and m[1] == 0:  # 首列合并
                                                        whether_shift = True
                                                    elif m[0] == real_row and m[1] < real_col:  # 当前列之前合并
                                                        whether_shift = True
                                                if whether_shift:  # 首列合并、当前列之前合并，赋值单元格位置 +1
                                                    new_col = real_col + (cols - temp_cols)
                                                else:
                                                    new_col = real_col
                                            else:
                                                new_col = real_col
                                            table.cell(real_row, new_col).text = soup_col.text
                            else:
                                str_line += 1
                    elif not isinstance(soup.contents[i].img, int) and soup.contents[i].img:  # 图片
                        image_info = soup.contents[i].img.attrs
                        # width = image_info.get("width") if image_info.get("width") else 5
                        # height = image_info.get("height") if image_info.get("height") else 5
                        img_str = image_info.get("src")

                        image_path = save_image(img_str, datetime.datetime.now().strftime('%Y%m%d%H%M%S%f'))
                        doc.add_picture(image_path, width=Inches(5))  # 添加图片
                        last_paragraph = doc.paragraphs[-1]
                        last_paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
                    else:
                        pass

    # doc.save(docx_path)


def str_to_json(styles):
    if styles:
        styles = styles.split(";")
        style = dict()
        for s in styles:
            s = s.split(":")
            if len(s) > 1:
                style[s[0].strip()] = s[1].strip()
        return style
    else:
        None


def move_table_after(table, paragraph):
    tbl, p = table._tbl, paragraph._p
    p.addnext(tbl)


def delete_paragraph(paragraph):
    p = paragraph._element
    p.getparent().remove(p)
    p._p = p._element = None
